package com.zondy.mapgis.psmap.manager.service.impl;

import cn.hutool.core.lang.Dict;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zondy.mapgis.common.core.utils.JsonUtils;
import com.zondy.mapgis.common.core.utils.StringUtils;
import com.zondy.mapgis.domain.psmap.*;
import com.zondy.mapgis.domain.system.SysUser;
import com.zondy.mapgis.psmap.manager.mapper.AppStoreMapper;
import com.zondy.mapgis.psmap.manager.mapper.AppStoreWidgetMapper;
import com.zondy.mapgis.psmap.manager.mapper.AppThemeMapper;
import com.zondy.mapgis.psmap.manager.mapper.AppWidgetMapper;
import com.zondy.mapgis.psmap.manager.service.IAppDataService;
import com.zondy.mapgis.psmap.manager.service.IAppStoreService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class AppStoreServiceImpl extends ServiceImpl<AppStoreMapper, AppStore> implements IAppStoreService {
   @Autowired
   private AppStoreMapper appStoreMapper;
   @Autowired
   private AppThemeMapper appThemeMapper;
   @Autowired
   private AppWidgetMapper appWidgetMapper;
   @Autowired
   private AppStoreWidgetMapper appStoreWidgetMapper;
   @Autowired
   private IAppDataService appDataService;
   private final String mapWidgetGroupName = "mapWidgetGroup";
   private final String widgetFolderType = "folder";

   @Override
   public AppStore selectAppStoreByAppId(Long appId) {
      return this.appStoreMapper.selectAppStoreByAppId(appId);
   }

   @Override
   public List<AppStore> selectAppStoreList(AppStore appStore) {
      return this.appStoreMapper.selectAppStoreList(appStore);
   }

   @Override
   public int insertAppStore(AppStore appStore) {
      return this.appStoreMapper.insertAppStore(appStore);
   }

   @Override
   public int updateAppStore(AppStore appStore) {
      return this.appStoreMapper.updateAppStore(appStore);
   }

   @Override
   public int deleteAppStoreByAppIds(Long[] appIds) {
      return this.appStoreMapper.deleteAppStoreByAppIds(appIds);
   }

   @Override
   public int deleteAppStoreByAppId(Long appId) {
      return this.appStoreMapper.deleteAppStoreByAppId(appId);
   }

   @Override
   public Dict fillupAppStore(AppStore appStore, Long userId) {
      String appConfig = appStore.getAppConfig();
      Dict dictAppConfig = JsonUtils.parseMap(appConfig);
      AppStoreWidget appStoreWidget = new AppStoreWidget();
      List<AppStoreWidget> authorizedAppWidgetList;
      if (SysUser.isAdmin(userId)) {
         authorizedAppWidgetList = this.appStoreWidgetMapper.selectAppStoreWidgetList(appStoreWidget);
      } else {
         appStoreWidget.getParams().put("userId", userId);
         authorizedAppWidgetList = this.appStoreWidgetMapper.selectAppStoreWidgetListByUserId(appStoreWidget);
      }

      this.fillupAppTheme((LinkedHashMap)dictAppConfig.get("theme"));
      this.fillupMapWidgets((LinkedHashMap)dictAppConfig.get("mapWidgets"), authorizedAppWidgetList);
      this.fillupContentWidgets((LinkedHashMap)dictAppConfig.get("contentWidgets"), authorizedAppWidgetList);
      this.fillupData(dictAppConfig, userId);
      return dictAppConfig;
   }

   @Override
   public String extractAppStore(String appConfig, String operName) {
      Dict dictAppConfig = JsonUtils.parseMap(appConfig);
      List<AppStoreWidgetTreeNode> appStoreWidgetTree = new ArrayList<>();
      this.extractAppTheme((LinkedHashMap)dictAppConfig.get("theme"), appStoreWidgetTree);
      this.appStoreWidgetMapper.cleanAppStoreWidget();
      this.extractMapWidgets((LinkedHashMap)dictAppConfig.get("mapWidgets"), this.findAppStoreWidgetTreeNodeByContentName(appStoreWidgetTree, "mapWidgetGroup"), operName);
      this.extractContentWidgets((LinkedHashMap)dictAppConfig.get("contentWidgets"), appStoreWidgetTree, operName);
      dictAppConfig.remove("data");
      return JsonUtils.toJsonString(dictAppConfig);
   }

   @Override
   public AppStoreWidget getAppWidget(String appWidgetId, String widgetName) {
      AppStoreWidget appStoreWidget = null;
      if (StringUtils.isNotEmpty(appWidgetId)) {
         appStoreWidget = this.appStoreWidgetMapper.selectAppStoreWidgetByAppWidgetId(appWidgetId);
      }

      if (StringUtils.isNull(appStoreWidget) && StringUtils.isNotEmpty(widgetName)) {
         appStoreWidget = this.appStoreWidgetMapper.selectAppStoreWidgetByWidgetName(widgetName);
      }

      return appStoreWidget;
   }

   @Override
   public Object getAppWidgetConfig(AppStoreWidget appStoreWidget) {
      String appWidgetConfig = appStoreWidget.getAppWidgetConfig();
      if (StringUtils.isEmpty(appWidgetConfig)) {
         appWidgetConfig = appStoreWidget.getWidget().getConfig();
         if (StringUtils.isEmpty(appWidgetConfig)) {
            return null;
         }
      }

      Object widgetConfigObject;
      if (appWidgetConfig.startsWith("[")) {
         widgetConfigObject = JsonUtils.parseArrayMap(appWidgetConfig);
      } else {
         widgetConfigObject = JsonUtils.parseMap(appWidgetConfig);
      }

      return widgetConfigObject;
   }

   private void fillupAppTheme(LinkedHashMap<String, Object> dictTheme) {
      if (dictTheme != null) {
         AppTheme appTheme = this.appThemeMapper.selectAppThemeByThemeName((String)dictTheme.get("name"));
         if (appTheme != null) {
            dictTheme.put("manifest", JsonUtils.parseMap(appTheme.getManifest()));
         }

      }
   }

   private void fillupMapWidgets(LinkedHashMap<String, Object> dictMapWidgets, List<AppStoreWidget> authorizedAppWidgetList) {
      if (dictMapWidgets != null) {
         this.fillupWidgets((List)dictMapWidgets.get("widgets"), authorizedAppWidgetList);
      }
   }

   private void fillupContentWidgets(LinkedHashMap<String, Object> dictContentWidgets, List<AppStoreWidget> authorizedAppWidgetList) {
      if (dictContentWidgets != null) {
         this.fillupContentGroupsWidgets((List)dictContentWidgets.get("groups"), authorizedAppWidgetList);
      }
   }

   private void fillupData(Dict dictAppConfig, Long userId) {
      List<AppDataTreeNode> appDataTreeNodes = this.appDataService.selectAppDataTreeForMapByUserId(userId);
      List<Dict> dictList = JsonUtils.parseArrayMap(JsonUtils.toJsonString(appDataTreeNodes));
      List<LinkedHashMap<String, Object>> dataList = (List<LinkedHashMap<String, Object>>) dictList.get(0).get("children");
      if (StringUtils.isNull(dataList)) {
         dataList = new ArrayList<>();
      }

      dictAppConfig.put("data", dataList);
   }

   private void formatAppDataTreeNodes(List<LinkedHashMap<String, Object>> dataList) {

       for (LinkedHashMap<String, Object> stringObjectLinkedHashMap : dataList) {
           LinkedHashMap data = stringObjectLinkedHashMap;
           String layerProperty = (String) data.get("layerProperty");
           String extend = (String) data.get("extend");
           List<LinkedHashMap<String, Object>> children = (List) data.get("children");
           if (StringUtils.isNotEmpty(layerProperty)) {
               data.put("layerProperty", JsonUtils.parseMap(layerProperty));
           }

           if (StringUtils.isNotEmpty(extend)) {
               data.put("extend", JsonUtils.parseMap(extend));
           }

           if (StringUtils.isNotEmpty(children)) {
               this.formatAppDataTreeNodes(children);
           }
       }

   }

   private void fillupContentGroupsWidgets(List<LinkedHashMap<String, Object>> dictContentGroupsWidgets, List<AppStoreWidget> authorizedAppWidgetList) {

       for (LinkedHashMap<String, Object> dictContentGroupsWidget : dictContentGroupsWidgets) {
           LinkedHashMap dictContentGroupWidgets = dictContentGroupsWidget;
           this.fillupWidgets((List) dictContentGroupWidgets.get("widgets"), authorizedAppWidgetList);
           this.removeUnauthorizedAppWidgets((List) dictContentGroupWidgets.get("widgetStructure"), authorizedAppWidgetList);
       }

   }

   private void fillupWidgets(List<LinkedHashMap<String, Object>> dictWidgets, List<AppStoreWidget> authorizedAppWidgetList) {
      Iterator<LinkedHashMap<String, Object>> iter = dictWidgets.iterator();

      while(iter.hasNext()) {
         LinkedHashMap<String, Object> dictWidget = iter.next();
         String appWidgetId = (String)dictWidget.get("id");
         String widgetName = (String)dictWidget.get("uri");
         if (StringUtils.isNotEmpty(appWidgetId) && StringUtils.isNotEmpty(widgetName)) {
            List<AppStoreWidget> filtered = authorizedAppWidgetList.stream().filter((appWidget) -> appWidget.getAppWidgetId().equals(appWidgetId)).collect(Collectors.toList());
            if (StringUtils.isNotEmpty(filtered)) {
               this.fillupWidget(dictWidget);
            } else {
               iter.remove();
            }
         }
      }

   }

   private void fillupWidget(LinkedHashMap<String, Object> dictWidget) {
      String appWidgetId = (String)dictWidget.get("id");
      String widgetName = (String)dictWidget.get("uri");
      if (!StringUtils.isEmpty(appWidgetId) && !StringUtils.isEmpty(widgetName)) {
         if (StringUtils.startsWith(widgetName, "widgets/")) {
            widgetName = widgetName.replace("widgets/", "");
         }

         AppStoreWidget appStoreWidget = this.appStoreWidgetMapper.selectAppStoreWidgetByAppWidgetId(appWidgetId);
         if (StringUtils.isNotNull(appStoreWidget)) {
            AppWidget appWidget = appStoreWidget.getWidget();
            if (StringUtils.isNotNull(appWidget) && widgetName.equals(appWidget.getWidgetName())) {
               String widgetConfig = appStoreWidget.getAppWidgetConfig();
               String widgetManifest = appWidget.getManifest();
               if (StringUtils.isEmpty(widgetConfig) || !JsonUtils.isJson(widgetConfig)) {
                  widgetConfig = appWidget.getConfig();
               }

               dictWidget.put("manifest", JsonUtils.parseMap(widgetManifest));
               if (StringUtils.isNotEmpty(widgetConfig)) {
                  Object widgetConfigObject;
                  if (widgetConfig.startsWith("[")) {
                     widgetConfigObject = JsonUtils.parseArrayMap(widgetConfig);
                  } else {
                     widgetConfigObject = JsonUtils.parseMap(widgetConfig);
                  }

                  dictWidget.put("config", widgetConfigObject);
               }
            }
         }

      }
   }

   private void removeUnauthorizedAppWidgets(List<LinkedHashMap<String, Object>> dictWidgets, List<AppStoreWidget> authorizedAppWidgetList) {
      if (dictWidgets != null && !dictWidgets.isEmpty()) {
         Iterator<LinkedHashMap<String, Object>> iter = dictWidgets.iterator();

         while(iter.hasNext()) {
            LinkedHashMap<String, Object> dictWidget = iter.next();
            String widgetType = (String)dictWidget.get("type");
            String widgetId = (String)dictWidget.get("id");
            List<LinkedHashMap<String, Object>> childWidgets = (List)dictWidget.get("children");
            if ("folder".equals(widgetType)) {
               this.removeUnauthorizedAppWidgets(childWidgets, authorizedAppWidgetList);
            } else if (StringUtils.isNotEmpty(widgetId)) {
               List<AppStoreWidget> filtered = authorizedAppWidgetList.stream().filter((appWidget) -> appWidget.getAppWidgetId().equals(widgetId)).collect(Collectors.toList());
               if (StringUtils.isEmpty(filtered)) {
                  iter.remove();
               }
            }
         }

      }
   }

   private void extractAppTheme(LinkedHashMap<String, Object> dictTheme, List<AppStoreWidgetTreeNode> appStoreWidgetTree) {
      if (dictTheme != null) {
         dictTheme.remove("manifest");
         AppTheme appTheme = this.appThemeMapper.selectAppThemeByThemeName((String)dictTheme.get("name"));
         if (StringUtils.isNotNull(appTheme)) {
            Dict dictThemeManifest = JsonUtils.parseMap(appTheme.getManifest());
            if (StringUtils.isNotNull(dictThemeManifest)) {
               List<LinkedHashMap<String, Object>> dictThemeManifestContents = (List)dictThemeManifest.get("contents");

                for (LinkedHashMap<String, Object> themeManifestContent : dictThemeManifestContents) {
                    AppStoreWidgetTreeNode appStoreWidgetTreeNode = new AppStoreWidgetTreeNode();
                    appStoreWidgetTreeNode.setIsFolder(true);
                    appStoreWidgetTreeNode.setName((String) themeManifestContent.get("name"));
                    appStoreWidgetTreeNode.setLabel((String) themeManifestContent.get("description"));
                    appStoreWidgetTree.add(appStoreWidgetTreeNode);
                }
            }
         }

         AppStoreWidgetTreeNode mapNode = new AppStoreWidgetTreeNode();
         mapNode.setIsFolder(true);
         mapNode.setName("mapWidgetGroup");
         mapNode.setLabel("地图");
         appStoreWidgetTree.add(mapNode);
      }
   }

   private void extractMapWidgets(LinkedHashMap<String, Object> dictMapWidgets, AppStoreWidgetTreeNode groupTreeNode, String operName) {
      if (dictMapWidgets != null) {
         this.extractWidgets((List)dictMapWidgets.get("widgets"), groupTreeNode, operName);
      }
   }

   private void extractContentWidgets(LinkedHashMap<String, Object> dictContentWidgets, List<AppStoreWidgetTreeNode> appStoreWidgetTree, String operName) {
      if (dictContentWidgets != null) {
         this.extractContentGroupsWidgets((List)dictContentWidgets.get("groups"), appStoreWidgetTree, operName);
      }
   }

   private void extractContentGroupsWidgets(List<LinkedHashMap<String, Object>> dictContentGroupsWidgets, List<AppStoreWidgetTreeNode> appStoreWidgetTree, String operName) {

       for (LinkedHashMap<String, Object> dictContentGroupsWidget : dictContentGroupsWidgets) {
           AppStoreWidgetTreeNode groupTreeNode = this.findAppStoreWidgetTreeNodeByContentName(appStoreWidgetTree, (String) dictContentGroupsWidget.get("content"));
           if (StringUtils.isNotNull(groupTreeNode)) {
               this.fillupAppStoreWidgetTree((List) dictContentGroupsWidget.get("widgetStructure"), groupTreeNode);
               this.extractWidgets((List) dictContentGroupsWidget.get("widgets"), groupTreeNode, operName);
           }
       }

   }

   private void extractWidgets(List<LinkedHashMap<String, Object>> dictWidgets, AppStoreWidgetTreeNode groupTreeNode, String operName) {

       for (LinkedHashMap<String, Object> widget : dictWidgets) {
           LinkedHashMap dictWidget = widget;
           this.extractWidget(dictWidget, groupTreeNode, operName);
       }

   }

   private void extractWidget(LinkedHashMap<String, Object> dictWidget, AppStoreWidgetTreeNode groupTreeNode, String operName) {
      String appWidgetId = (String)dictWidget.get("id");
      String widgetName = (String)dictWidget.get("uri");
      if (!StringUtils.isEmpty(appWidgetId) && !StringUtils.isEmpty(widgetName)) {
         if (StringUtils.startsWith(widgetName, "widgets/")) {
            widgetName = widgetName.replace("widgets/", "");
         }

         AppStoreWidget appStoreWidget = new AppStoreWidget();
         appStoreWidget.setAppWidgetId(appWidgetId);
         AppWidget appWidget = this.appWidgetMapper.selectAppWidgetByWidgetName(widgetName);
         if (StringUtils.isNotNull(appWidget)) {
            appStoreWidget.setWidgetId(appWidget.getWidgetId());
            Object widgetConfigObject = dictWidget.get("config");
            if (StringUtils.isNotNull(widgetConfigObject)) {
               String widgetConfig = JsonUtils.toJsonString(widgetConfigObject);
               if (StringUtils.isNotEmpty(widgetConfig)) {
                  String defaultWidgetConfig = appWidget.getConfig();
                  if (StringUtils.isEmpty(defaultWidgetConfig) || !this.isConfigEqual(defaultWidgetConfig, widgetConfig)) {
                     appStoreWidget.setAppWidgetConfig(widgetConfig);
                  }

                  dictWidget.remove("config");
               }
            }

            appStoreWidget.setCreateBy(operName);
            appStoreWidget.setAppWidgetLocation(this.getWidgetLocationByWidgetId(groupTreeNode, appWidgetId));
            this.appStoreWidgetMapper.insertAppStoreWidget(appStoreWidget);
         }

         dictWidget.remove("manifest");
      } else {
         dictWidget.remove("manifest");
      }
   }

   private boolean isConfigEqual(String config1, String config2) {
      ObjectMapper mapper = new ObjectMapper();
      JsonNode jsonNode1 = null;
      JsonNode jsonNode2 = null;

      try {
         jsonNode1 = mapper.readTree(config1);
         jsonNode2 = mapper.readTree(config2);
      } catch (JsonProcessingException var7) {
      }

      return jsonNode1.equals(jsonNode2);
   }

   private void fillupAppStoreWidgetTree(List<LinkedHashMap<String, Object>> widgets, AppStoreWidgetTreeNode appStoreWidgetTree) {
      AppStoreWidgetTreeNode treeNode;
      if (widgets != null) {
         for(Iterator var3 = widgets.iterator(); var3.hasNext(); appStoreWidgetTree.children.add(treeNode)) {
            LinkedHashMap widget = (LinkedHashMap)var3.next();
            String widgetType = (String)widget.get("type");
            String widgetId = (String)widget.get("id");
            List<LinkedHashMap<String, Object>> childWidgets = (List)widget.get("children");
            treeNode = new AppStoreWidgetTreeNode();
            treeNode.setId(widgetId);
            if (!"folder".equals(widgetType) && !StringUtils.isNotEmpty(childWidgets)) {
               treeNode.setIsFolder(false);
               widget.remove("manifest");
               widget.remove("config");
            } else {
               treeNode.setLabel((String)widget.get("label"));
               treeNode.setIsFolder(true);
               this.fillupAppStoreWidgetTree(childWidgets, treeNode);
            }
         }
      }

   }

   private AppStoreWidgetTreeNode findAppStoreWidgetTreeNodeByContentName(List<AppStoreWidgetTreeNode> appStoreWidgetTree, String content) {
      return appStoreWidgetTree.stream().filter(e -> content.equals(e.getName())).findAny().orElse(null);
   }

   private String getWidgetLocationByWidgetId(AppStoreWidgetTreeNode groupTreeNode, String appWidgetId) {
      if (StringUtils.isEmpty(groupTreeNode.getChildren())) {
         return groupTreeNode.getLabel();
      } else {
         String widgetLocation = this.getWidgetSubLocationByWidgetId(groupTreeNode.getLabel(), groupTreeNode.getChildren(), appWidgetId);
         return StringUtils.isEmpty(widgetLocation) ? groupTreeNode.getLabel() : widgetLocation;
      }
   }

   private String getWidgetSubLocationByWidgetId(String groupLabel, List<AppStoreWidgetTreeNode> groupTree, String appWidgetId) {

       for (AppStoreWidgetTreeNode child : groupTree) {
           if (child != null && StringUtils.isNotEmpty(child.getId())) {
               if (child.getId().equals(appWidgetId)) {
                   return groupLabel;
               }

               if (child.getIsFolder()) {
                   String subLocation = this.getWidgetSubLocationByWidgetId(child.getLabel(), child.getChildren(), appWidgetId);
                   if (StringUtils.isNotEmpty(subLocation)) {
                       return groupLabel + "/" + subLocation;
                   }
               }
           }
       }

      return "";
   }

   private static class AppStoreWidgetTreeNode {
      private String id;
      private String name;
      private String label;
      private Boolean isFolder;
      private List<AppStoreWidgetTreeNode> children = new ArrayList();

      public AppStoreWidgetTreeNode() {
      }

      public String getId() {
         return this.id;
      }

      public String getName() {
         return this.name;
      }

      public String getLabel() {
         return this.label;
      }

      public Boolean getIsFolder() {
         return this.isFolder;
      }

      public List<AppStoreWidgetTreeNode> getChildren() {
         return this.children;
      }

      public void setId(String id) {
         this.id = id;
      }

      public void setName(String name) {
         this.name = name;
      }

      public void setLabel(String label) {
         this.label = label;
      }

      public void setIsFolder(Boolean isFolder) {
         this.isFolder = isFolder;
      }

      public void setChildren(List<AppStoreWidgetTreeNode> children) {
         this.children = children;
      }

      @Override
      public boolean equals(Object o) {
         if (o == this) {
            return true;
         } else if (!(o instanceof AppStoreWidgetTreeNode)) {
            return false;
         } else {
            AppStoreWidgetTreeNode other = (AppStoreWidgetTreeNode)o;
            if (!other.canEqual(this)) {
               return false;
            } else {
               label71: {
                  Object this$isFolder = this.getIsFolder();
                  Object other$isFolder = other.getIsFolder();
                  if (this$isFolder == null) {
                     if (other$isFolder == null) {
                        break label71;
                     }
                  } else if (this$isFolder.equals(other$isFolder)) {
                     break label71;
                  }

                  return false;
               }

               Object this$id = this.getId();
               Object other$id = other.getId();
               if (this$id == null) {
                  if (other$id != null) {
                     return false;
                  }
               } else if (!this$id.equals(other$id)) {
                  return false;
               }

               label57: {
                  Object this$name = this.getName();
                  Object other$name = other.getName();
                  if (this$name == null) {
                     if (other$name == null) {
                        break label57;
                     }
                  } else if (this$name.equals(other$name)) {
                     break label57;
                  }

                  return false;
               }

               Object this$label = this.getLabel();
               Object other$label = other.getLabel();
               if (this$label == null) {
                  if (other$label != null) {
                     return false;
                  }
               } else if (!this$label.equals(other$label)) {
                  return false;
               }

               Object this$children = this.getChildren();
               Object other$children = other.getChildren();
               if (this$children == null) {
                  if (other$children == null) {
                     return true;
                  }
               } else if (this$children.equals(other$children)) {
                  return true;
               }

               return false;
            }
         }
      }

      protected boolean canEqual(Object other) {
         return other instanceof AppStoreWidgetTreeNode;
      }

      @Override
      public int hashCode() {
         int result = 1;
         Object $isFolder = this.getIsFolder();
         result = result * 59 + ($isFolder == null ? 43 : $isFolder.hashCode());
         Object $id = this.getId();
         result = result * 59 + ($id == null ? 43 : $id.hashCode());
         Object $name = this.getName();
         result = result * 59 + ($name == null ? 43 : $name.hashCode());
         Object $label = this.getLabel();
         result = result * 59 + ($label == null ? 43 : $label.hashCode());
         Object $children = this.getChildren();
         result = result * 59 + ($children == null ? 43 : $children.hashCode());
         return result;
      }

      @Override
      public String toString() {
         return "AppStoreServiceImpl.AppStoreWidgetTreeNode(id=" + this.getId() + ", name=" + this.getName() + ", label=" + this.getLabel() + ", isFolder=" + this.getIsFolder() + ", children=" + this.getChildren() + ")";
      }
   }
}
